﻿
using System;

namespace Peony
{
    public class ByteBuffer
    {
        Int32 BUFFERSIZE = 65535;
        public byte[] _buffs { get; private set; }
        public Int32 _iMaxIndex { get; private set; }
        public Int32 _iReadIdx { get; private set; }
        public Int32 _iWriteIdx { get; private set; }
        private Object _lock = new object();
        public ByteBuffer()
        {
            _buffs = new byte[BUFFERSIZE];
            _iMaxIndex = BUFFERSIZE - 1;
            _iReadIdx = 0;
            _iWriteIdx = 0;
        }

        public Int32 PeekByte(byte[] pData, Int32 iCount)
        {
            lock (_lock)
            {
                if (isEmpty()) return -1;

                if (iCount <= 0 || pData.Length < iCount) return -1;
                if (CanReadSize() < iCount) return -1;
                Array.Copy(_buffs,_iReadIdx,pData,0,iCount);
                return iCount;
            }
        }

        public void HasRead(Int32 iCount)
        {
            lock (_lock)
            {
                _iReadIdx += iCount;
            }
        }

        public Int32 CanReadSize()
        {
            return _iWriteIdx - _iReadIdx;
        }

        public Int32 putByte(byte[] pData, Int32 iCount)
        {
            lock (_lock)
            {
                if (iCount <= 0 || pData.Length <= 0) return -1;
                checkFull(iCount);
                Array.Copy(pData,0,_buffs,_iWriteIdx,iCount);
                _iWriteIdx += iCount;
                return iCount;
            }
        }

        public Int32 getByte(byte[] pData, Int32 iCount)
        {

            PeekByte(pData, iCount);
            HasRead(iCount);
            return iCount;
        }


        public bool isEmpty()
        {
            return (_iWriteIdx - _iReadIdx) == 0;
        }

        void checkFull(Int32 count)
        {
            if (_iWriteIdx + count > _iMaxIndex)
            {
                if (isEmpty())
                {
                    _iReadIdx = 0;
                    _iWriteIdx = 0;
                }
                else
                {
                    //计算出未读取的长度
                    Int32 unReadSize = CanReadSize();
                    Int32 frontSpace = _iReadIdx;
                    if (unReadSize > frontSpace)
                    {//如果未读取的长度 大于写入长度,需要开辟更大空间
                        byte[] BiggerBuffer = new byte[_buffs.Length*2];
                        Array.Copy(_buffs,_iReadIdx,BiggerBuffer,0,unReadSize);
                        _iMaxIndex = BiggerBuffer.Length - 1;
                        _buffs = BiggerBuffer;
                    }
                    else
                    {//将未读取数据迁移到头部
                        Array.Copy(_buffs,_iReadIdx,_buffs,0,unReadSize);
                    }
                    _iReadIdx = 0;
                    _iWriteIdx = unReadSize;
                }
            }
        }

    }

}
